package com.waylau.spring.boot.blog.controller;

import java.sql.*;
import java.sql.Date;
import java.util.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;

import com.hankcs.hanlp.HanLP;
import com.waylau.spring.boot.blog.domain.*;
import com.waylau.spring.boot.blog.service.*;
import com.waylau.spring.boot.blog.util.HanLPUtil;
import com.waylau.spring.boot.blog.util.MailUtil;
import com.waylau.spring.boot.blog.vo.BlogImgVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.method.P;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import com.waylau.spring.boot.blog.util.ConstraintViolationExceptionHandler;
import com.waylau.spring.boot.blog.vo.Response;

/**
 * 用户主页空间控制器.
 *
 * @since 1.0.0 2017年3月25日
 * @author <a href="https://waylau.com">Way Lau</a>
 */
@Controller
@RequestMapping("/u")
public class UserspaceController {
	@Autowired
	private UserDetailsService userDetailsService;

	@Autowired
	private UserService userService;

	@Autowired
	private BlogService blogService;

	@Autowired
	private CatalogService catalogService;

	@Autowired
	private GenreService genreService;

	@Autowired
	private BrowseService browseService;

	@Autowired
	private HanLPUtil hanLPUtil;

	@Value("${justice}")
	private String justice;


	@GetMapping("/{username}")
	public String userSpace(@PathVariable("username") String username, Model model) {
		User  user = (User)userDetailsService.loadUserByUsername(username);
		model.addAttribute("user", user);
		return "redirect:/u/" + username + "/blogs";
	}

	@GetMapping("/{username}/profile")
	@PreAuthorize("authentication.name.equals(#username)")
	public ModelAndView profile(@PathVariable("username") String username, Model model) {
		User  user = (User)userDetailsService.loadUserByUsername(username);
		model.addAttribute("user", user);
		return new ModelAndView("/userspace/profile", "userModel", model);
	}

	/**
	 * 保存个人设置
	 * @param user
	 * @return
	 */
	@PostMapping("/{username}/profile")
	@PreAuthorize("authentication.name.equals(#username)")
	public String saveProfile(@PathVariable("username") String username,User user) {
		User originalUser = userService.getUserById(user.getId());
		originalUser.setEmail(user.getEmail());
		originalUser.setName(user.getName());

		// 判断密码是否做了变更
		String rawPassword = originalUser.getPassword();
		PasswordEncoder  encoder = new BCryptPasswordEncoder();
		String encodePasswd = encoder.encode(user.getPassword());
		boolean isMatch = encoder.matches(rawPassword, encodePasswd);
		if (!isMatch) {
			originalUser.setEncodePassword(user.getPassword());
		}

		userService.saveUser(originalUser);
		return "redirect:/u/" + username + "/profile";
	}

	/**
	 * 获取编辑头像的界面
	 * @param username
	 * @param model
	 * @return
	 */
	@GetMapping("/{username}/avatar")
	@PreAuthorize("authentication.name.equals(#username)")
	public ModelAndView avatar(@PathVariable("username") String username, Model model) {
		User  user = (User)userDetailsService.loadUserByUsername(username);
		model.addAttribute("user", user);
		return new ModelAndView("/userspace/avatar", "userModel", model);
	}


	/**
	 * 保存头像
	 * @param username
	 * @return
	 */
	@PostMapping("/{username}/avatar")
	@PreAuthorize("authentication.name.equals(#username)")
	public ResponseEntity<Response> saveAvatar(@PathVariable("username") String username, @RequestBody User user) {
		String avatarUrl = user.getAvatar();

		User originalUser = userService.getUserById(user.getId());
		originalUser.setAvatar(avatarUrl);
		userService.saveUser(originalUser);

		return ResponseEntity.ok().body(new Response(true, "处理成功", avatarUrl));
	}


	@GetMapping("/{username}/blogs")
	public String listBlogsByOrder(@PathVariable("username") String username,
								   @RequestParam(value="order",required=false,defaultValue="new") String order,
								   @RequestParam(value="catalog",required=false ) Long catalogId,
								   @RequestParam(value="keyword",required=false,defaultValue="" ) String keyword,
								   @RequestParam(value="async",required=false) boolean async,
								   @RequestParam(value="pageIndex",required=false,defaultValue="0") int pageIndex,
								   @RequestParam(value="pageSize",required=false,defaultValue="10") int pageSize,
								   Model model) {

		User  user = (User)userDetailsService.loadUserByUsername(username);

		Page page = null;

		if (catalogId != null && catalogId > 0) {
			// 分类查询
			Catalog catalog = catalogService.getCatalogById(catalogId);
			Pageable pageable = new PageRequest(pageIndex, pageSize);
			page = blogService.listBlogsByCatalog(catalog, pageable);
			order = "";
		} else if ("hot".equals(order)) {
			// 最热查询
			Sort sort = new Sort(Direction.DESC,"readSize","commentSize","voteSize");
			Pageable pageable = new PageRequest(pageIndex, pageSize, sort);
			page = blogService.listBlogsByTitleVoteAndSort(user, keyword, pageable);
		} else if ("new".equals(order)) {
			// 最新查询
			Pageable pageable = new PageRequest(pageIndex, pageSize);
			page = blogService.listBlogsByTitleVote(user, keyword, pageable);
		} else if ("collect".equals(order)){
			// 查看我的收藏
			Pageable pageable = new PageRequest(pageIndex, pageSize);
			user = userService.getUserById(user.getId());
			Collection<Long> ids = new ArrayList<Long>();
			user.getCollectBlogs().forEach(a->{
				ids.add(a.getId());
			});
			page = blogService.listBlogsByIds(ids,pageable);
		} else if("follow".equals(order)){
			user = userService.getUserById(user.getId());
			Pageable pageable = new PageRequest(pageIndex, pageSize);
			Collection<Long> ids = new ArrayList<Long>();
			user.getUsers().forEach(a->{
				ids.add(a.getId());
			});
			page = userService.listUsersByIds(ids,pageable);
		}


		List<Blog> list = page.getContent();	// 当前所在页面数据列表

		model.addAttribute("follow", false);
		model.addAttribute("me",false);
		Authentication auth = SecurityContextHolder.getContext().getAuthentication();
		if (!(auth instanceof AnonymousAuthenticationToken)) {
			User loginUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
			if(loginUser.getId().equals(user.getId())){
				model.addAttribute("me",true);
			}
			for(User follow: loginUser.getUsers()){
				if(follow.getId().equals(user.getId())){
					model.addAttribute("follow", true);
					break;
				}
			}
		}
		model.addAttribute("user", user);
		model.addAttribute("order", order);
		model.addAttribute("catalogId", catalogId);
		model.addAttribute("keyword", keyword);
		model.addAttribute("page", page);
		model.addAttribute("blogList", list);
		return (async==true?"/userspace/u :: #mainContainerRepleace":"/userspace/u");
	}

	/**
	 * 获取博客展示界面
	 * @param id
	 * @param model
	 * @return
	 */
	@GetMapping("/{username}/blogs/{id}")
	public String getBlogById(@PathVariable("username") String username,@PathVariable("id") Long id, Model model) {
		User principal = null;
		Blog blog = blogService.getBlogById(id);

		model.addAttribute("isCollect", false);

		// 每次读取，简单的可以认为阅读量增加1次
		blogService.readingIncrease(id);

		Object object = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		if(!"anonymousUser".equals(object)){
			User user = (User) object;
			Browse browse = new Browse();
			browse.setUserId(user.getId());
			browse.setBlogId(blog.getId());
			browse.setGenreId(blog.getGenre().getId());
			browse.setTime(new Date(System.currentTimeMillis()));
			browseService.save(browse);

			user = userService.getUserById(user.getId());
			user.getCollectBlogs().forEach(a->{
				if(id.equals(a.getId())){
					model.addAttribute("isCollect", true);
				}
			});

		}
		// 判断操作用户是否是博客的所有者
		boolean isBlogOwner = false;
		if (SecurityContextHolder.getContext().getAuthentication() !=null && SecurityContextHolder.getContext().getAuthentication().isAuthenticated()
				&&  !SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString().equals("anonymousUser")) {
			principal = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
			if (principal !=null && username.equals(principal.getUsername())) {
				isBlogOwner = true;
			}
		}

		// 判断操作用户的点赞情况
		List<Vote> votes = blog.getVotes();
		Vote currentVote = null; // 当前用户的点赞情况

		if (principal !=null) {
			for (Vote vote : votes) {
				if(vote.getUser().getUsername().equals(principal.getUsername())){
					currentVote = vote;
					break;
				}
			}
		}

		model.addAttribute("isBlogOwner", isBlogOwner);
		model.addAttribute("blogModel",blog);
		model.addAttribute("currentVote",currentVote);

		for(Comment comment : blog.getComments()){
			System.out.println(comment.getUser().getAvatar());
		}

		return "/userspace/blog";
	}

	/**
	 * 收藏博客
	 * @param blogId
	 * @return
	 */
	@PostMapping("/collect")
	public ResponseEntity<Response> collectBlog(Long blogId){

		try {
			blogService.collectBlog(blogId);
		}catch (DataIntegrityViolationException e)  {
			return ResponseEntity.ok().body(new Response(false, "不能重复收藏"));
		}catch (ConstraintViolationException e)  {
			return ResponseEntity.ok().body(new Response(false, ConstraintViolationExceptionHandler.getMessage(e)));
		} catch (Exception e) {
			return ResponseEntity.ok().body(new Response(false, e.getMessage()));
		}
		return ResponseEntity.ok().body(new Response(true, "收藏成功", null));
	}

	/**
	 * 收藏博客
	 * @param blogId
	 * @return
	 */
	@PostMapping("/cancelCollect")
	public ResponseEntity<Response> cancelCollectBlog(Long blogId){
		try {
			blogService.cancelCollectBlog(blogId);
		}catch (ConstraintViolationException e)  {
			return ResponseEntity.ok().body(new Response(false, ConstraintViolationExceptionHandler.getMessage(e)));
		} catch (Exception e) {
			return ResponseEntity.ok().body(new Response(false, e.getMessage()));
		}
		return ResponseEntity.ok().body(new Response(true, "处理成功", null));
	}

	/**
	 * 用户关注
	 * @param followName
	 * @return
	 */
	@PostMapping("/follow")
	public ResponseEntity<Response> follow(String followName){

		try {
			userService.follow(followName);
		}catch (DataIntegrityViolationException e)  {
			return ResponseEntity.ok().body(new Response(false, "不能重复关注"));
		}catch (ConstraintViolationException e)  {
			return ResponseEntity.ok().body(new Response(false, ConstraintViolationExceptionHandler.getMessage(e)));
		} catch (Exception e) {
			return ResponseEntity.ok().body(new Response(false, e.getMessage()));
		}
		return ResponseEntity.ok().body(new Response(true, "处理成功", null));
	}

	/**
	 * 用户取消关注
	 * @param followId
	 * @return
	 */
	@PostMapping("/cancelFollow")
	public ResponseEntity<Response> cancelfollow(Long followId){

		try {
			userService.cancelFollow(followId);
		}catch (DataIntegrityViolationException e)  {
			return ResponseEntity.ok().body(new Response(false, "不能重复取消关注"));
		}catch (ConstraintViolationException e)  {
			return ResponseEntity.ok().body(new Response(false, ConstraintViolationExceptionHandler.getMessage(e)));
		} catch (Exception e) {
			return ResponseEntity.ok().body(new Response(false, e.getMessage()));
		}
		return ResponseEntity.ok().body(new Response(true, "处理成功", null));
	}



	/**
	 * 删除博客
	 * @param id
	 * @return
	 */
	@DeleteMapping("/{username}/blogs/{id}")
	@PreAuthorize("authentication.name.equals(#username)")
	public ResponseEntity<Response> deleteBlog(@PathVariable("username") String username,@PathVariable("id") Long id) {

		try {
			blogService.removeBlog(id);
		} catch (Exception e) {
			return ResponseEntity.ok().body(new Response(false, e.getMessage()));
		}

		String redirectUrl = "/u/" + username + "/blogs";
		return ResponseEntity.ok().body(new Response(true, "处理成功", redirectUrl));
	}

	/**
	 * 获取新增博客的界面
	 * @param model
	 * @return
	 */
	@GetMapping("/{username}/blogs/edit")
	public ModelAndView createBlog(@PathVariable("username") String username, Model model) {
		User user = (User)userDetailsService.loadUserByUsername(username);
		List<Catalog> catalogs = catalogService.listCatalogs(user);
		List<Genre> genres = genreService.findAvailableGenres();

		model.addAttribute("blog", new Blog(null, null, null));
		model.addAttribute("genres", genres);
		model.addAttribute("catalogs", catalogs);
		return new ModelAndView("/userspace/blogedit", "blogModel", model);
	}

	/**
	 * 获取编辑博客的界面
	 * @param model
	 * @return
	 */
	@GetMapping("/{username}/blogs/edit/{id}")
	public ModelAndView editBlog(@PathVariable("username") String username, @PathVariable("id") Long id, Model model) {
		// 获取用户分类列表
		User user = (User)userDetailsService.loadUserByUsername(username);
		List<Catalog> catalogs = catalogService.listCatalogs(user);
		List<Genre> genres = genreService.findAvailableGenres();

		model.addAttribute("blog", blogService.getBlogById(id));
		model.addAttribute("genres", genres);
		model.addAttribute("catalogs", catalogs);
		return new ModelAndView("/userspace/blogedit", "blogModel", model);
	}

	/**
	 * 保存博客
	 * @param username
	 * @return
	 */
	@PostMapping("/{username}/blogs/edit")
	@PreAuthorize("authentication.name.equals(#username)")
	public ResponseEntity<Response> saveBlog(@PathVariable("username") String username, @RequestBody Map<String ,Object> map) {

		Blog oldBlog = null;

		Blog blog = new Blog();
		if(map.get("id")!=null&&map.get("id").toString().trim().length()>0){
			blog.setId(Long.parseLong(map.get("id").toString()));
			oldBlog = blogService.getBlogById(Long.parseLong(map.get("id").toString()));
		}
		if(map.get("title")!=null){
			blog.setTitle(map.get("title").toString());
			String key = findSensitiveWord(blog.getTitle());
			if(key!=null){
				return ResponseEntity.ok().body(new Response(false,"标题包含敏感词 "+key));
			}
		}
		if(map.get("summary")!=null){
			blog.setSummary(map.get("summary").toString());
			String key = findSensitiveWord(blog.getSummary());
			if(key!=null){
				return ResponseEntity.ok().body(new Response(false,"摘要包含敏感词 "+key));
			}
		}
		if(map.get("type")!=null){
			blog.setType(Integer.parseInt(map.get("type").toString()));
		}
		if(map.get("content")!=null){
			blog.setContent(map.get("content").toString());
			String key = findSensitiveWord(blog.getContent());
			if(key!=null){
				return ResponseEntity.ok().body(new Response(false,"正文包含敏感词 "+key));
			}
			Map<String,String> imgMap = new HashMap<String,String>();//key:imgName  value: imgId
			//如果是编辑 则对原有图片进行继承处理
			if(oldBlog!=null){
				String htmlContent = oldBlog.getHtmlContent();
				System.out.println(htmlContent);
				while(htmlContent.indexOf("data-imgname")>0&&htmlContent.indexOf("data-imgid")>0){
					String imgName = htmlContent.substring(htmlContent.indexOf("data-imgname")+14,htmlContent.indexOf("data-imgid")-2);
					String imgId = htmlContent.substring(htmlContent.indexOf("data-imgid")+12,htmlContent.indexOf("data-imgid")+48);
					System.out.println(imgName);
					System.out.println(imgId);
					htmlContent = htmlContent.substring(0,htmlContent.indexOf("data-imgname"))+ htmlContent.substring(htmlContent.indexOf("data-imgid")+49);
					imgMap.put(imgName,imgId);
				}
			}
			//对新增图片进行处理
			if(map.get("imgs")!=null){
				String htmlContent = blog.getHtmlContent();
				ArrayList<LinkedHashMap> imgs = (ArrayList<LinkedHashMap>) map.get("imgs");
				for (LinkedHashMap img:imgs) {
					imgMap.put(img.get("imgName").toString(),img.get("imgId").toString());
				}
			}
			if (imgMap.size()>0){
				String htmlContent = blog.getHtmlContent();

				Set<String> imgNames = imgMap.keySet();

				for (String imgName:imgNames) {
					String imgHtml = "<img src=\""+imgName+"\"" ;
					if(htmlContent.indexOf(imgHtml)>0){
						htmlContent = htmlContent.substring(0,htmlContent.indexOf(imgHtml)) +"<img data-imgname=\""+imgName+"\" data-imgid=\"" + imgMap.get(imgName) + "\" "+ htmlContent.substring(htmlContent.indexOf(imgHtml)+imgHtml.length()+1);
					}
				}
				blog.setHtmlContent(htmlContent);
			}
		}
		if(map.get("catalogId")!=null&&map.get("catalogId").toString().trim().length()>0){
			Catalog catalog = new Catalog();
			catalog.setId(Long.parseLong(map.get("catalogId").toString()));
			blog.setCatalog(catalog);
		}
		if(map.get("genreId")!=null&&map.get("genreId").toString().trim().length()>0){
			Genre genre = new Genre();
			genre.setId(Long.parseLong(map.get("genreId").toString()));
			blog.setGenre(genre);
		}
		if(map.get("tags")!=null){
			blog.setTags(map.get("tags").toString());
		}
		// 对 Catalog 进行空处理
		if (blog.getCatalog().getId() == null) {
			return ResponseEntity.ok().body(new Response(false,"未选择分类"));
		}
		try {
			// 判断是修改还是新增
			if (blog.getId()!=null) {
				Blog orignalBlog = blogService.getBlogById(blog.getId());
				orignalBlog.setTitle(blog.getTitle());
				String htmlContent = blog.getHtmlContent();
				orignalBlog.setContent(blog.getContent());
				orignalBlog.setHtmlContent(htmlContent);
				orignalBlog.setSummary(blog.getSummary());
				orignalBlog.setCatalog(blog.getCatalog());
				orignalBlog.setGenre(blog.getGenre());
				orignalBlog.setTags(blog.getTags());
				orignalBlog.setType(blog.getType());
				blogService.saveBlog(orignalBlog);
			} else {
				User user = (User)userDetailsService.loadUserByUsername(username);
				blog.setUser(user);
				blogService.saveBlog(blog);
			}
		} catch (ConstraintViolationException e)  {
			return ResponseEntity.ok().body(new Response(false, ConstraintViolationExceptionHandler.getMessage(e)));
		} catch (Exception e) {
			return ResponseEntity.ok().body(new Response(false, e.getMessage()));
		}
		String redirectUrl = "/u/" + username + "/blogs/" + blog.getId();
		return ResponseEntity.ok().body(new Response(true, "处理成功", redirectUrl));
	}


	/**
	 * find 敏感词
	 * @param text
	 * @return
	 */
	private String findSensitiveWord(String text){
		List<String> keys = new ArrayList<>();
		keys.addAll(hanLPUtil.getMainIdea(text,10));
		keys.addAll(hanLPUtil.getDuanYu(text,10));
		for(String key : keys){
			if(justice.indexOf(key)>=0){
				return key;
			}
		}
		return null;
	}

}
